/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   OSEndianTools.inl. Created on: 15.06.2009 13:21:04
*/


#ifndef OSENDIANTOOLS_INL_
#define OSENDIANTOOLS_INL_


namespace cpputils {
	namespace utils {

#ifndef HAVE_NTOHLL
		inline boost::uint64_t ntohll_f(boost::uint64_t value ) {
			if(OSEndianTools::isLittleEndianArch())
		        return ((((boost::uint64_t)ntohl((boost::uint32_t)value)) << 32) + ntohl( (boost::uint32_t)(value >> 32)));
		    else /* big endian */
		        return value;
		}

		inline boost::uint64_t htonll_f(boost::uint64_t value) {
			if(OSEndianTools::isLittleEndianArch())
		        return ((((boost::uint64_t)htonl((boost::uint32_t)value)) << 32) + htonl( (boost::uint32_t)(value >> 32)));
		    else
		        return value;
		}
#else
	#define ntohll_f ntohll
	#define htonll_f htonll
#endif

		bool OSEndianTools::isBigEndianArch() {
#if !defined(BOOST_BIG_ENDIAN) && !defined(BOOST_LITTLE_ENDIAN)
		    int endianDetector = 1;

		    /* little endian */
		    if(*(char *)&endianDetector == 1)
		    	return false;
		    else
		    	/* big endian */
		    	return true;
#else
	#ifdef BOOST_BIG_ENDIAN
			return true;
	#else
			return false;
	#endif
#endif
		}

		bool OSEndianTools::isLittleEndianArch() {
			return !isBigEndianArch();
		}

		boost::int16_t OSEndianTools::network_to_host(boost::int16_t value) {
			return network_to_host( (boost::uint16_t) value);
		}

		boost::int32_t OSEndianTools::network_to_host(boost::int32_t value) {
			return network_to_host( (boost::uint32_t) value);
		}

		boost::int64_t OSEndianTools::network_to_host(boost::int64_t value) {
			return network_to_host( (boost::uint64_t) value);
		}

		boost::uint16_t OSEndianTools::network_to_host(boost::uint16_t value) {
			return ntohs ( value );
		}

		boost::uint32_t OSEndianTools::network_to_host(boost::uint32_t value) {
			return ntohl ( value );
		}

		boost::uint64_t OSEndianTools::network_to_host(boost::uint64_t value) {
			return ntohll_f(value);
		}

		float OSEndianTools::network_to_host(float value) {
			FloatIntFormat result;
			result.fValue = value;
			result.nValue = network_to_host ( result.nValue );
			return result.fValue;
		}

		double OSEndianTools::network_to_host(double value) {
			DoubleIntFormat result;
			result.fValue = value;
			result.nValue = network_to_host ( result.nValue );
			return result.fValue;
		}

		boost::int16_t OSEndianTools::host_to_network(boost::int16_t value) {
			return host_to_network( (boost::uint16_t) value );
		}

		boost::int32_t OSEndianTools::host_to_network(boost::int32_t value) {
			return host_to_network( (boost::uint32_t) value );
		}

		boost::int64_t OSEndianTools::host_to_network(boost::int64_t value) {
			return host_to_network( (boost::uint64_t) value );
		}

		boost::uint16_t OSEndianTools::host_to_network(boost::uint16_t value) {
			return htons ( value );
		}

		boost::uint32_t OSEndianTools::host_to_network(boost::uint32_t value) {
			return htonl ( value );
		}

		boost::uint64_t OSEndianTools::host_to_network(boost::uint64_t value) {
			return htonll_f ( value );
		}

		float OSEndianTools::host_to_network(float value) {
			FloatIntFormat result;
			result.fValue = value;
			result.nValue = host_to_network ( result.nValue );
			return result.fValue;
		}

		double OSEndianTools::host_to_network(double value) {
			DoubleIntFormat result;
			result.fValue = value;
			result.nValue = host_to_network ( result.nValue );
			return result.fValue;
		}
	}
}

#endif /* OSENDIANTOOLS_INL_ */
